/**
 *抽象工厂模式（Abstract Factory Pattern）是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式，它提供了一种创建对象的最佳方式。

在抽象工厂模式中，接口是负责创建一个相关对象的工厂，不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象。


 意图：提供一个创建一系列相关或相互依赖对象的接口，而无需指定它们具体的类。

主要解决：主要解决接口选择的问题。

何时使用：系统的产品有多于一个的产品族，而系统只消费其中某一族的产品。

如何解决：在一个产品族里面，定义多个产品。

关键代码：在一个工厂里聚合多个同类产品。


优点：当一个产品族中的多个对象被设计成一起工作时，它能保证客户端始终只使用同一个产品族中的对象。

缺点：产品族扩展非常困难，要增加一个系列的某一产品，既要在抽象的 Creator 里加代码，又要在具体的里面加代码。

使用场景： 1、QQ 换皮肤，一整套一起换。 2、生成不同操作系统的程序。

注意事项：产品族难扩展，产品等级易扩展。
 */
namespace 抽象工厂模式 {
    // 第一步, 为形状创建一个接口
    interface Shape {
        draw: Function;
    }

    //第二步, 创建实现接口的实体类
    class RectAngle implements Shape {
        public draw() {
            console.log("画个长方形");
        }
    }

    class Square implements Shape {
        public draw() {
            console.log("画个正方形");
        }
    }

    class Circle implements Shape {
        public draw() {
            console.log("圆形");
        }
    }


    // 步骤三 ,  为颜色创建一个接口
    interface Color {
        fill: Function;
    }

    // 步骤四 创建实现接口的实体类
    class Red implements Color {
        public fill() {
            console.log("红色的 fill");
        }
    }

    class Green implements Color {
        public fill() {
            console.log("green的fill方法");
        }
    }

    class Blue implements Color {
        public fill() {
            console.log("Blue的fill方法");
        }
    }


    //步骤5 为 Color 和Shape 创建抽象类来获取工厂
    abstract class AbstratFactory {
        public abstract getColor(color: string): Color | null;
        public abstract getShape(shape: string): Shape | null;
    }

    //步骤6 创建扩展了AbstractFactory的工厂类, 基于给定的信息生成实体类对象
    class ShapeFactory extends AbstratFactory {
        public getShape(shape: string) {
            if (shape == null) {
                return null;
            }

            switch (shape) {
                case "CIRCLE":
                    return new Circle();
                case "RECTANGLE":
                    return new RectAngle();
                case "SQUARE":
                    return new Square();
                default:
                    break;
            }

            return null;
        }
        public getColor(color: string) {
            return null;
        }
    }

    class ColorFactory extends AbstratFactory {
        public getShape() {
            return null;
        }
        public getColor(color: string) {
            if (color == null) {
                return null;
            }
            switch (color) {
                case "red":
                    return new Red();
                    break;
                case "green":
                    return new Green();
                case "blue":
                    return new Blue();
                default:
                    break;
            }
            return null;
        }
    }

    //步骤7 创建一个工厂创造器/生成器类, 通过传递形状或颜色信息来获取工厂
    class FactoryProducer {
        public static getFactory(choice: string) {
            if (choice == "SHAPE") {
                return new ShapeFactory();
            } else if (choice == "COLOR") {
                return new ColorFactory();
            }
            return null;
        }
    }

    // 步骤8 , 使用 FactoryProducer 获取AbstractFactory, 通过传递类型信息来获取实体类的对象
    let shapeFactory = FactoryProducer.getFactory("SHAPE");
    let shape1 = shapeFactory?.getShape("CIRCLE");
    shape1?.draw();

    let shape2 = shapeFactory?.getShape("RECTANGLE");
    shape2?.draw();

    let shape3 = shapeFactory?.getShape("SQUARE");
    shape3?.draw();


    //颜色工厂模式
    let colorFactory = FactoryProducer.getFactory("COLOR");

    let color1 = colorFactory?.getColor("red");
    color1?.fill();

    let green = colorFactory?.getColor("green");
    green?.fill();

    let blue = colorFactory?.getColor("blue");
    blue?.fill();

}




